import { databases, DATABASE_ID, COLLECTIONS } from '../config/appwrite';
import { ID, Query, Permission, Role } from 'appwrite';

export type TicketStatus = 'open' | 'in-progress' | 'resolved' | 'closed';
export type TicketPriority = 'low' | 'medium' | 'high' | 'urgent';
export type TicketCategory = 'technical' | 'billing' | 'account' | 'feature' | 'other';

export interface Ticket {
  $id: string;
  userId: string;
  userEmail: string;
  userName: string;
  subject: string;
  category: TicketCategory;
  priority: TicketPriority;
  status: TicketStatus;
  description: string;
  $createdAt: string;
  $updatedAt: string;
}

export interface TicketMessage {
  $id: string;
  ticketId: string;
  userId: string;
  userName: string;
  message: string;
  isStaff: boolean;
  $createdAt: string;
}

export interface CreateTicketData {
  subject: string;
  category: TicketCategory;
  priority: TicketPriority;
  description: string;
  userEmail?: string;
}

export interface CreateMessageData {
  ticketId: string;
  message: string;
}

class TicketService {
  /**
   * Create a new support ticket
   */
  async createTicket(data: CreateTicketData, userId: string, userName: string, userEmail: string) {
    try {
      const ticket = await databases.createDocument(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        ID.unique(),
        {
          userId,
          userEmail: data.userEmail || userEmail,
          userName,
          subject: data.subject,
          category: data.category,
          priority: data.priority,
          status: 'open' as TicketStatus,
          description: data.description,
        },
        [
          // Document-level permissions - user can read/update their own ticket
          Permission.read(Role.user(userId)),
          Permission.update(Role.user(userId)),
          // Admins and moderators can read/update all tickets
          Permission.read(Role.label('admin')),
          Permission.read(Role.label('moderator')),
          Permission.update(Role.label('admin')),
          Permission.update(Role.label('moderator')),
        ]
      );

      return { success: true, ticket };
    } catch (error) {
      console.error('Create ticket failed:', error);
      return { success: false, error };
    }
  }

  /**
   * Get user's tickets with pagination
   */
  async getUserTickets(userId: string, page: number = 1, limit: number = 10) {
    try {
      const offset = (page - 1) * limit;
      
      const response = await databases.listDocuments(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        [
          Query.equal('userId', userId),
          Query.orderDesc('$createdAt'),
          Query.limit(limit),
          Query.offset(offset),
        ]
      );

      return { 
        success: true, 
        tickets: response.documents as unknown as Ticket[],
        total: response.total 
      };
    } catch (error) {
      console.error('Get user tickets failed:', error);
      return { success: false, error, tickets: [], total: 0 };
    }
  }

  /**
   * Get all tickets (admin only)
   */
  async getAllTickets(page: number = 1, limit: number = 10, status?: TicketStatus) {
    try {
      const offset = (page - 1) * limit;
      const queries = [
        Query.orderDesc('$createdAt'),
        Query.limit(limit),
        Query.offset(offset),
      ];

      if (status) {
        queries.push(Query.equal('status', status));
      }

      const response = await databases.listDocuments(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        queries
      );

      return { 
        success: true, 
        tickets: response.documents as unknown as Ticket[],
        total: response.total 
      };
    } catch (error) {
      console.error('Get all tickets failed:', error);
      return { success: false, error, tickets: [], total: 0 };
    }
  }

  /**
   * Get a single ticket by ID
   */
  async getTicket(ticketId: string) {
    try {
      const ticket = await databases.getDocument(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        ticketId
      );

      return { success: true, ticket: ticket as unknown as Ticket };
    } catch (error) {
      console.error('Get ticket failed:', error);
      return { success: false, error };
    }
  }

  /**
   * Update ticket status
   */
  async updateTicketStatus(ticketId: string, status: TicketStatus) {
    try {
      const ticket = await databases.updateDocument(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        ticketId,
        { status }
      );

      return { success: true, ticket };
    } catch (error) {
      console.error('Update ticket status failed:', error);
      return { success: false, error };
    }
  }

  /**
   * Add a message to a ticket
   */
  async createMessage(data: CreateMessageData, userId: string, userName: string, isStaff: boolean = false) {
    try {
      const message = await databases.createDocument(
        DATABASE_ID,
        COLLECTIONS.TICKET_MESSAGES,
        ID.unique(),
        {
          ticketId: data.ticketId,
          userId,
          userName,
          message: data.message,
          isStaff,
        },
        [
          // Get the ticket to find the owner
          // For now, allow the message creator and staff to read
          Permission.read(Role.user(userId)),
          Permission.read(Role.label('admin')),
          Permission.read(Role.label('moderator')),
        ]
      );

      // Update ticket's updatedAt timestamp
      await databases.updateDocument(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        data.ticketId,
        {} // Empty update to trigger $updatedAt
      );

      return { success: true, message };
    } catch (error) {
      console.error('Create message failed:', error);
      return { success: false, error };
    }
  }

  /**
   * Get messages for a ticket
   */
  async getTicketMessages(ticketId: string) {
    try {
      const response = await databases.listDocuments(
        DATABASE_ID,
        COLLECTIONS.TICKET_MESSAGES,
        [
          Query.equal('ticketId', ticketId),
          Query.orderAsc('$createdAt'),
        ]
      );

      return { 
        success: true, 
        messages: response.documents as unknown as TicketMessage[] 
      };
    } catch (error) {
      console.error('Get ticket messages failed:', error);
      return { success: false, error, messages: [] };
    }
  }

  /**
   * Delete a ticket (admin only)
   */
  async deleteTicket(ticketId: string) {
    try {
      // Delete all messages first
      const messagesResponse = await databases.listDocuments(
        DATABASE_ID,
        COLLECTIONS.TICKET_MESSAGES,
        [Query.equal('ticketId', ticketId)]
      );

      for (const message of messagesResponse.documents) {
        await databases.deleteDocument(
          DATABASE_ID,
          COLLECTIONS.TICKET_MESSAGES,
          message.$id
        );
      }

      // Delete the ticket
      await databases.deleteDocument(
        DATABASE_ID,
        COLLECTIONS.TICKETS,
        ticketId
      );

      return { success: true };
    } catch (error) {
      console.error('Delete ticket failed:', error);
      return { success: false, error };
    }
  }

  /**
   * Get ticket statistics
   */
  async getTicketStats(userId?: string) {
    try {
      const queries = userId ? [Query.equal('userId', userId)] : [];
      
      const [allTickets, openTickets, inProgressTickets, resolvedTickets] = await Promise.all([
        databases.listDocuments(DATABASE_ID, COLLECTIONS.TICKETS, queries),
        databases.listDocuments(DATABASE_ID, COLLECTIONS.TICKETS, [...queries, Query.equal('status', 'open')]),
        databases.listDocuments(DATABASE_ID, COLLECTIONS.TICKETS, [...queries, Query.equal('status', 'in-progress')]),
        databases.listDocuments(DATABASE_ID, COLLECTIONS.TICKETS, [...queries, Query.equal('status', 'resolved')]),
      ]);

      return {
        success: true,
        stats: {
          total: allTickets.total,
          open: openTickets.total,
          inProgress: inProgressTickets.total,
          resolved: resolvedTickets.total,
        }
      };
    } catch (error) {
      console.error('Get ticket stats failed:', error);
      return { 
        success: false, 
        error,
        stats: { total: 0, open: 0, inProgress: 0, resolved: 0 }
      };
    }
  }
}

export const ticketService = new TicketService();
